#ifndef ___fat32_procesar_senal

#define ___fat32_procesar_senal 1

#include <signal.h>
#include <stdio.h>
#include <time.h>

void fat32_procesar_senal(void);
void fat32_procesar_senal_recibida(void);
char * fat32_hora_actual(void);
void fat32_mostrar_contenido_bloque(FILE *, char, void *);

#define fat32_imprimir_caracter(ARCH, CAR) ((((CAR) < 32) || ((CAR) > 126)) ? putc('.', (ARCH)) : putc((CAR), (ARCH)))

void fat32_procesar_senal (void) {
  sigset_t s;
  sigemptyset(&s);
  sigaddset(&s, SIGUSR1);
  struct timespec t;
  t.tv_sec = t.tv_nsec = 0;
  int resultado = sigtimedwait(&s, NULL, &t);
  if (resultado != -1) fat32_procesar_senal_recibida();
}

void fat32_procesar_senal_recibida (void) {
  char * hora = fat32_hora_actual;
  FILE * archivo = fopen("cache_dump.txt", "a+");
  if (!archivo) return;
  fprintf(archivo, "Hora de solicitud de volcado de cache: %s\n", hora);
  free(hora);
  unsigned char cantidadBloques = fat32_cache.cantidadBloques;
  unsigned char posicion;
  if (!cantidadBloques) {
    fprintf(archivo, "No hay cache habilitada.\n");
    fprintf(archivo, "---------------------------------------------------------------------\n");
    fclose(archivo);
    return;
  }
  fprintf(archivo, "Cantidad de bloques de cache: %hhu\n\n", cantidadBloques);
  fprintf(archivo, "ID Numero bloque\n");
  fprintf(archivo, "-- -------------\n");
  for (posicion = 0; posicion < cantidadBloques; posicion ++) {
    fprintf(archivo, " %c ", (posicion < 10) ? (posicion + 48) : (posicion + 55));
    if (fat32_cache.control[posicion].estado == 255)
      fprintf(archivo, " No asignado \n");
    else
      fprintf(archivo, "   %10lu\n", fat32_cache.control[posicion].sectorInicial);
  }
  fprintf(archivo, "\n");
  fprintf(archivo, "Contenido bloques: (aclaracion: las direcciones estan en formato\nnumero:desplazamiento, en hexadecimal)\n\n");
  for (posicion = 0; posicion < cantidadBloques; posicion ++) {
    char id = posicion;
    id += (posicion < 10) ? 48 : 55;
    fat32_mostrar_contenido_bloque(id, fat32_cache.datos + (2048 * posicion));
  }
  fprintf(archivo, "---------------------------------------------------------------------\n");
  fclose(archivo);
}

char * fat32_hora_actual(void) {
  time_t hora = time(NULL);
  struct tm datos = localtime(hora);
  char * resultado = malloc(15);
  sprintf(resultado, "%d:%02d:%02d", datos.tm_hour, datos.tm_min, datos.tm_sec);
  return resultado;
}

void fat32_mostrar_contenido_bloque (FILE * archivo, char IDbloque, void * datosBloque) {
  char * d = datosBloque;
  unsigned int p1, p2;
  for (p1 = 0; p1 < 128; p1 ++) {
    fprintf(archivo, "%c:%03X ", IDbloque, p1 * 16);
    for (p2 = 0; p2 < 16; p2 ++)
      fprintf(archivo, "%02hhX ", d[p1 * 16 + p2]);
    for (p2 = 0; p2 < 16; p2 ++)
      fat32_imprimir_caracter(archivo, d[p1 * 16 + p2]);
    putc('\n', archivo);
  }
}

#endif